﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BLToolkit.Data;
using BLToolkit.Data.DataProvider;
using System.Data;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using nwrole.toolbox.sync.extensions;

namespace nwrole.toolbox.sync
{
    public class GhostFileSync : GhostTableSyncXXX
    {

        public SyncResult SyncDirectUpdate(SyncMap map, Func<byte[], string, string, int> callback)
        {
            SyncResult result = new SyncResult();
            try
            {
                string sourceFileName = "tableName" + ".bin";
                string destinationFileName = System.IO.Path.GetTempFileName();
                long fileSize = 0;
                BinaryReader ghostReader = null;
                if (File.Exists(sourceFileName))
                {
                    ghostReader = new BinaryReader(File.OpenRead(sourceFileName));
                    fileSize = new FileInfo(sourceFileName).Length;
                }
                var ghostWriter = new BinaryWriter(File.Create(destinationFileName));

                using (DbManager db = new DbManager(sourceDataProvider, SourceConnectionString))
                {
                    db.SetCommand("select cast(texterid as integer) as TexterId, Relid, Text, TexterTypId from wf.floff3 order by TexterId asc");
                    // db.SetCommand("select , TexterTypid, Relid, Text from wf.texter where tabellnamn = 'Objekt'");
                    // db.SetCommand("select texterid, TexterTypid, Relid, Text from wf.texter where tabellnamn = 'Objekt'");
                    db.SetCommand("select dbms_lob.substr(TEXT, 4000,1) as Text from floff3");
                    IDataReader reader = db.ExecuteReader();
                    while (reader.Read())
                    {
                        // TODO: what is this good for? 20120924
                        object fff = reader["Text"];
                    }

                    int counter = 0;
                    bool timeToRead = true;
                    // decimal ghostTexterId = ghostReader.ReadDecimal();

                    decimal ghostTexterId = -1;
                    string ghostText = "";
                    decimal ghostRelid = -1;
                    decimal ghostTexterTypId = -1;

                    BinaryFormatter serializationFormatter = new BinaryFormatter();
                    MemoryStream buffer = new MemoryStream();
                    string schema = map.GetSchema();

                    object[] row = null;
                    while (reader.Read())
                    {
                        if (row == null)
                        {
                            row = new object[reader.FieldCount];
                        }

                        bool diff = false;

                        decimal TexterId = (decimal)reader["TexterId"];
                        ghostWriter.Write(TexterId);

                        decimal Relid = (decimal)reader["Relid"];
                        ghostWriter.Write(Relid);

                        string Text = reader["Text"].ToString();
                        /*if ((Text != null) && (Text.Length > 0)) {
                            int fgfg = 1;
                        }*/
                        ghostWriter.Write(Text);

                        decimal TexterTypId = (decimal)reader["TexterTypId"];
                        ghostWriter.Write(TexterTypId);

                        if (timeToRead)
                        {
                            do
                            {
                                if ((ghostReader!=null) && (ghostReader.BaseStream.Position < fileSize))
                                {
                                    ghostTexterId = ghostReader.ReadDecimal();
                                    ghostText = ghostReader.ReadString();
                                    ghostRelid = ghostReader.ReadDecimal();
                                    ghostTexterTypId = ghostReader.ReadDecimal();
                                    timeToRead = false;
                                }
                            } while ((ghostTexterId < TexterId) && (ghostTexterId != -1));
                        } 

                        if (TexterId.Equals(ghostTexterId))
                        {
                            if (!Text.Equals(ghostText)) diff = true;
                            if (!Relid.Equals(ghostRelid)) diff = true;
                            if (!TexterTypId.Equals(ghostTexterTypId)) diff = true;
                            timeToRead = true;
                        }
                        else
                        {

                            diff = true;
                        } 

                        if (diff)
                        {
                            // we found a record to send to the client
                            for (int t = 0; t < reader.FieldCount; t++)
                            {
                                var col = map.Columns[t];
                                row[t] = reader[t];
                            }
                            serializationFormatter.Serialize(buffer, row);
                            if (buffer.Length > 1000000)
                            {
                                callback(buffer.ToArray(), map.Name, schema);
                                buffer.SetLength(0);
                            }
                        }

                        counter++;
                        if ((counter % 100) == 0)
                            Console.Write(".");
                    }

                    if (buffer.Length > 0)
                    {
                        callback(buffer.ToArray(), map.Name, schema);
                        buffer.SetLength(0);
                    }

                    if (ghostReader != null)
                    {
                        ghostReader.Close();
                    }
                    ghostWriter.Close();
                    File.Delete(sourceFileName);
                    File.Copy(destinationFileName, sourceFileName);
                }
            }
            catch
            {
            }
            return result;
        }
    }
}
